package com.itheima.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(1)
//控制顺序，数字越小，优先级越高
public class AscepDemo2 {
    //新的注解就是：将切入点表达式进行抽取（因为一段一段的书写，比较繁琐）----注释为:Printcut
        @Pointcut("execution(* com.itheima.service.impl.*.*(..))")

        //接下来就是空的方法
        public void pt(){}
    //通知类型（@around  @Before  @After  @AfterReturning @AfterThrowing）

/*
* @Around环绕通知1：此主机标注的通知方法在目标方法前 后都被执行
* @Before前置执行2：次注解标注的通知方法在目标方法前被执行
* @After后置通知3：此注解标注的通知方法在目标方法后被执行，无论异常都会执行
* @AfterRetruning4:返回后通知，此注解标注的通知方法在目标方法后被执行，有异常不会执行
* @AfterThrowiing5:异常通知后，此注解标注的通知方法发生异常后执行
*
*
*   需要注意的就是@around注解就是环绕注解通知方法（但是需要返回值Object来接受，而且数据类型必须为Object）
*
*   现在需要注意的就是：设置多个切面执行的顺序--需要用到注解关键字Order()

*5)多个切面执行的顺序
        1)第一个 切面的前置逻辑先执行
        2)第二个切面的前置逻辑
        2)第二个切面的后置逻辑
        1)第一个 切面的后置逻辑先执行
            可以控制顺序(默认按照类名称自然排序)
        @order数值越小,优无级越高，优先级越高（说白了就是数值越小，优先执行哪一个）
*
*统一抽取切入点表达式
*           @Pointcut("execution(* com.itheima.service.impl.*.*(..))")
*           public void pt(){}
*
*           public 修饰：其他aop也能使用
*           private 修饰：当前类可以使用
*
*
* */
    @Before("pt()")
    public void Before(){
        System.out.println("前置通知");
    }
    @AfterReturning("pt()")
    public void AfterReturning(){
        System.out.println("目标方案正常执行后，后置通知");
    }
    @AfterThrowing("pt()")
    public void AfterThrowing(){
        System.out.println("目标方法抛出异常后，异常通知");
    }
    @After("pt()")
    public void After(){
        System.out.println("目标方法不管抛不抛出异常最终都是会通知，最终通知");
    }





    /*//目标方法

    //around的就是将目标方法包裹起来----现在就是创建目标对象
   @Around("execution(* com.itheima.service.impl.*.*(..))")
    public Object around(ProceedingJoinPoint pjp ){
       try {
           System.out.println("前置通知");
           //目标方法（调用目标方法）
           Object proceed = pjp.proceed();
           System.out.println("目标方案正常执行后，后置通知");
                return proceed;
       } catch (Throwable e) {
           e.printStackTrace();
           System.out.println("目标方法抛出异常后，异常通知");
       }finally {
           System.out.println("目标方法不管抛不抛出异常最终都是会通知，最终通知");
       }
       return null;
   }*/

}
